import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from decimal import Decimal

from decimal import Decimal


def calculate_health_index(statement):
    """
    计算财务健康指数
    :param statement: 财务报表数据（可以是字典或Django模型实例）
    :return: 健康指数字典
    """
    # 判断传入的 statement 是否为字典或模型实例，并根据类型进行处理
    if isinstance(statement, dict):
        # 如果是字典
        net_profit = float(statement['net_profit'])
        revenue = float(statement['revenue'])
        total_assets = float(statement['total_assets'])
        total_liabilities = float(statement['total_liabilities'])
    else:
        # 如果是模型实例
        net_profit = statement.net_profit
        revenue = statement.revenue
        total_assets = statement.total_assets
        total_liabilities = statement.total_liabilities

    # 防止除数为零
    if revenue == 0:
        profitability = 0.0
    else:
        profitability = (net_profit / revenue) * 100.0  # 净利润与收入比率

    if total_liabilities == 0:
        solvency = 0.0
    else:
        solvency = (total_assets / total_liabilities) * 100.0  # 总资产与负债比率

    if total_assets == 0:
        efficiency = 0.0
    else:
        efficiency = (net_profit / total_assets) * 100.0  # 净利润与总资产比率

    # 对指数进行归一化或加权平均
    overall_health = (profitability * 0.3 + solvency * 0.4 + efficiency * 0.3)

    # 返回健康指数字典
    return {
        'profitability_index': round(profitability, 2),
        'solvency_index': round(solvency, 2),
        'efficiency_index': round(efficiency, 2),
        'overall_health_index': round(overall_health, 2)
    }


def dynamic_weights(industry, company_size):
    """
    动态计算财务健康指数各项比率的权重
    :param industry: 行业类型（例如：'tech'、'manufacturing'等）
    :param company_size: 企业规模（例如：'large'、'small'等）
    :return: 权重字典
    """
    if industry == 'tech':
        profitability_weight = 0.4
        solvency_weight = 0.3
        efficiency_weight = 0.3
    elif industry == 'manufacturing':
        profitability_weight = 0.3
        solvency_weight = 0.4
        efficiency_weight = 0.3
    else:
        profitability_weight = 0.3
        solvency_weight = 0.3
        efficiency_weight = 0.4

    # 根据公司规模调整权重
    if company_size == 'large':
        profitability_weight *= 1.1  # 大公司更注重盈利能力
        solvency_weight *= 1.1  # 大公司更注重偿债能力
    elif company_size == 'small':
        efficiency_weight *= 1.1  # 小公司更注重效率

    # 确保权重之和为1
    total_weight = profitability_weight + solvency_weight + efficiency_weight
    profitability_weight /= total_weight
    solvency_weight /= total_weight
    efficiency_weight /= total_weight

    return {
        'profitability': profitability_weight,
        'solvency': solvency_weight,
        'efficiency': efficiency_weight
    }


def calculate_health_index_with_dynamic_weights(statement, industry, company_size):
    """
    使用动态权重计算财务健康指数
    :param statement: 财务报表数据
    :param industry: 行业类型
    :param company_size: 企业规模
    :return: 财务健康指数字典
    """
    # 获取动态权重
    weights = dynamic_weights(industry, company_size)

    # 计算财务比率
    profitability = (statement['net_profit'] / statement['revenue']) * 100
    solvency = (statement['total_assets'] / statement['total_liabilities']) * 100
    efficiency = (statement['net_profit'] / statement['total_assets']) * 100

    # 计算总体健康指数
    overall_health = (profitability * weights['profitability'] +
                      solvency * weights['solvency'] +
                      efficiency * weights['efficiency'])

    return {
        'profitability_index': round(profitability, 2),
        'solvency_index': round(solvency, 2),
        'efficiency_index': round(efficiency, 2),
        'overall_health_index': round(overall_health, 2)
    }


# 假设的历史财务数据，实际应用中需要根据实际数据训练
def train_risk_model():
    data = {
        'total_liabilities': [200000000, 100000000, 300000000, 150000000],
        'total_assets': [500000000, 400000000, 600000000, 450000000],
        'revenue': [100000000, 80000000, 120000000, 90000000],
        'operating_cash_flow': [20000000, 15000000, 25000000, 18000000],
        'risk_label': [1, 0, 1, 0]  # 0 = low risk, 1 = high risk
    }
    df = pd.DataFrame(data)

    # 特征和标签
    X = df[['total_liabilities', 'total_assets', 'revenue', 'operating_cash_flow']]
    y = df['risk_label']

    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    # 训练模型
    model = RandomForestClassifier()
    model.fit(X_train, y_train)

    # 预测并评估
    y_pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)

    print(f'Model Accuracy: {accuracy * 100:.2f}%')

    return model


# 计算负债风险
def calculate_debt_risk(statement):
    """
    使用机器学习模型来预测负债风险
    :param statement: 财务报表数据
    :return: 负债比率、利息覆盖比率、风险预测结果
    """
    debt_ratio = (statement['total_liabilities'] / statement['total_assets']) * 100  # 负债比率
    interest_coverage = statement['revenue'] / statement['operating_cash_flow']  # 利息覆盖比率

    # 使用训练好的模型进行风险预测
    features = [
        statement['total_liabilities'],
        statement['total_assets'],
        statement['revenue'],
        statement['operating_cash_flow']
    ]
    # 预测风险
    model = train_risk_model()
    risk_prediction = model.predict([features])[0]  # 0表示低风险，1表示高风险

    risk_level = 'High Risk' if risk_prediction == 1 else 'Low Risk'

    return {
        'debt_ratio': round(debt_ratio, 2),
        'interest_coverage': round(interest_coverage, 2),
        'risk_level': risk_level
    }


# 动态调整负债风险分析（根据行业类型）
def dynamic_weighted_debt_risk(statement, industry_type):
    """
    动态调整风险权重
    :param statement: 财务报表数据
    :param industry_type: 行业类型，用于调整权重
    :return: 加权后的风险分析结果
    """
    debt_ratio = (statement['total_liabilities'] / statement['total_assets']) * 100
    interest_coverage = statement['revenue'] / statement['operating_cash_flow']

    # 根据行业类型调整权重
    if industry_type == 'Tech':
        debt_weight = 0.3
        interest_weight = 0.7
    elif industry_type == 'Manufacturing':
        debt_weight = 0.6
        interest_weight = 0.4
    else:
        debt_weight = 0.5
        interest_weight = 0.5

    # 计算加权风险分数
    risk_score = debt_ratio * debt_weight + interest_coverage * interest_weight
    return round(risk_score, 2)
